﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using xKnight.Analyzing.Xss;
using xKnight.Data;
using xKnight.Models;

namespace xKnight.Analyzing.SimpleXss
{
    public class SimpleXssAnalyzer : Analyzer
    {
        #region Properties

        protected XssAnalyzingSharedResource SharedResource
        {
            get
            {
                return _analyzingSharedResource as XssAnalyzingSharedResource;
            }
        }

        #endregion

        #region Constructors

        internal SimpleXssAnalyzer(Attack attack)
            : base(attack)
        {
            
        }

        #endregion

        #region Interface

        public override void Analyze()
        {
            XAttack xAttack=null;
            while ((xAttack = GetNotAnalyzedAttack()) != null)
            {
                DoAnalyze(xAttack);
            }
        }

        protected override AnalyzingSharedResource CreateAnalyzingSharedResource(Attack attack)
        {
            object sharedLock = new object();

            XAttack[] xAttacks = DataLayer.GetXAttacks(attack);
            Queue<XAttack> sharedQueue = new Queue<XAttack>();

            for (int i = 0; i < xAttacks.Length; i++)
                sharedQueue.Enqueue(xAttacks[i]);

            XssAnalyzingSharedResource sharedResource = new XssAnalyzingSharedResource(sharedQueue, sharedLock, attack);

            return sharedResource;
        }

        #endregion

        #region Private Methods

        private void DoAnalyze(XAttack xAttack)
        {
            XAttackParam[] attackParams = DataLayer.GetAttackParams(xAttack);
            string response = xAttack.ResponsePage;
            xAttack.Succeed = HasReflectedVulnerablity(attackParams, response);

            DataLayer.Save(xAttack);

            SimpleXssAnalyzeAnnounceItem announceItem = new SimpleXssAnalyzeAnnounceItem
                (xAttack.Form.Action, xAttack.Form.Method, xAttack, "", DateTime.Now
                , xAttack.Succeed.Value, DataLayer.GetWebPage(xAttack.Form.Id).Url);

            OnAnalyzeAnnounced(announceItem);

        }

        protected virtual bool HasReflectedVulnerablity(XAttackParam[] attackParams, string response)
        {
            bool hasVulnerability = false;

            for (int i = 0; i < attackParams.Length && !hasVulnerability; i++)
            {
                if (response!=null
                    && attackParams[i].IsPoison
                    && response.IndexOf(attackParams[i].Value) > -1)
                    hasVulnerability= true;
            }

            return hasVulnerability;
        }

        protected virtual XAttack GetNotAnalyzedAttack()
        {
            XAttack xAttack = null;

            lock (SharedResource.SharedLock)
            {
                xAttack = SharedResource.SharedQueue.Count != 0 ? SharedResource.SharedQueue.Dequeue() : null;
            }

            return xAttack;
        }

        #endregion
    }
}
